Skip to content

Conversation

mateo-ivc
Copy link
Collaborator

Description

Changing the frontend api requests that a separation of user and session in the backend is possible

Changelog

backend

  • Separating user from session -> moving files into their own package

frontend

  • added extra API request to receive the missing Auth object
  • board/thunk.js -> biggest problem was here since (user)sessions now only contains the userID but the frontend needed the full user object => added extra API request where needed

Keep in mind that the frontend changes should not be kept like this. The goal is here to also refactor the frontend api in order to achieve the separation

Checklist

  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • The light- and dark-theme are both supported and tested
  • The design was implemented and is responsive for all devices and screen sizes
  • The application was tested in the most commonly used browsers (e.g. Chrome, Firefox, Safari)

(Optional) Visual Changes

@mateo-ivc mateo-ivc force-pushed the mi/seperate-user-from-session branch from 990b0ef to 207eb3a Compare September 26, 2025 07:27
@mateo-ivc mateo-ivc marked this pull request as ready for review September 26, 2025 07:27
Copy link

The deployment to the dev cluster was successful. You can find the deployment here: https://5403.development.scrumlr.fra.ics.inovex.io
This deployment is only for testing purposes and will be deleted after 1 week.
To redeploy rerun the workflow.
DO NOT STORE IMPORTANT DATA ON THIS DEPLOYMENT

Deployed Images
  • ghcr.io/inovex/scrumlr.io/scrumlr-frontend:sha-81c8b3f

  • ghcr.io/inovex/scrumlr.io/scrumlr-server:sha-81c8b3f

Copy link
Collaborator

@Planlos5000 Planlos5000 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Backend looks good

)

type DB struct {
type SessionDB struct {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rename to DB to be consistent

database UserDatabase
sessionService SessionService
realtime *realtime.Broker
type BoardSessionService struct {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rename to Service to be consistent

Comment on lines +58 to +78
const dtoToParticipant = async (dto: ParticipantDTO): Promise<Participant> => {
const user: Auth = await API.getUserById(dto.id);
return {
user,
connected: dto.connected,
raisedHand: dto.raisedHand,
ready: dto.ready,
showHiddenColumns: dto.showHiddenColumns,
role: dto.role,
banned: dto.banned,
};
};

const mapParticipantsWithUsers = async (message: BoardInitEvent): Promise<Participant[]> => {
const {participants} = message.data;
const asDTOs = participants as unknown as ParticipantDTO[];
const mapped = await Promise.all(asDTOs.map(dtoToParticipant));
message.data.participants = mapped;
return mapped;
};

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why don't we use batch fetching here instead of querying every user one after the other? With 10 participants, that's 10 separate API calls that could potentially be just one. What do you think about
the performance impact when boards get busy?

Similar pattern in the websocket handlers around line 178-186
I see we're doing the same sequential fetching in multiple places. Have you considered if there's a way we could consolidate this logic?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we going over to a batch API we could do something like this, to fix both, the performance and possible issues when participants aren't loading.

const mapParticipantsOptimized = async (dtos: ParticipantDTO[]): Promise<Participant[]> => {
    try {
      const userIds = dtos.map(dto => dto.id);
      const users = await API.getUsersByIds(userIds); 

      return dtos.map(dto => {
        const user = users.find((u: Auth) => u.id === dto.id);
        if (!user) {
          console.warn(`User not found for participant ${dto.id}`);
          return null;
        }
        return { user, ...dto };
      }).filter(Boolean) as Participant[];
    } catch (error) {
      console.error('Failed to map participants with users:', error);
      return [];
    }
  };

}
},

getUserById: async (userId: string) => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens if getUserById fails for one participant? Will it break the entire participant list update?

role: ParticipantRole;
banned?: boolean;
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you think about refactoring this to:

// (currently ParticipantDTO)
export interface ParticipantWithUserId {
    userId: string;  
    connected: boolean;
    ready: boolean;
    raisedHand: boolean;
    showHiddenColumns: boolean;
    role: ParticipantRole;
    banned?: boolean;
  }

// currently Participant
  export interface ParticipantWithUser {
    user: Auth;  // I also don't like the interface naming "Auth" but this isn't your problem.
    connected: boolean;
    ready: boolean;
    raisedHand: boolean;
    showHiddenColumns: boolean;
    role: ParticipantRole;
    banned?: boolean;
  }

I think, this is easier to understand. What is you opinion about this @Schwehn42?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants